package com.zyf.service;

import cn.hutool.core.io.FileUtil;
import com.zyf.service.audio.HandleAudioService;
import com.zyf.service.img.AddTextToImg;
import com.zyf.service.img.HandleImageMergeService;
import com.zyf.service.img.ImageHandle;
import com.zyf.service.video.HandleVideoService;
import com.zyf.service.video.VedioUtils;
import com.zyf.utils.FFmpegUtils;
import com.zyf.utils.ImageUtils;
import com.zyf.utils.PublicEnums;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.*;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MergeDataService {

    /**
     * 合成视频
     */
    public static String makeShortvedio(String imgPath, String autoPath, int mergeVedioType) {
        //读取添加文字后的图片,批量合成视频
        try {
            List<File> files = FileUtil.loopFiles(imgPath, file -> file.isFile() && (file.getName().contains(".jpg") || file.getName().contains(".png")));
            //合成视频先旋转图片
            RotateImage.rotateImgs(files, 270);
            int num = 1;
//            int width = 1300;
//            int height = 1600;
            //单张图片合成视频
            if (mergeVedioType == PublicEnums.MergeVedioType.SingleImg.getValue()) {
                for (File imgFile : files) {
                    BufferedImage image = ImageIO.read(imgFile);
                    //获取图片的像素数组
                    int width = image.getWidth();
                    int height = image.getHeight();
                    //图片输出路径
                    String mp4SavePath = imgPath + File.separator + "mergeImage.mp4";
                    //图片合成视频
                    try {
                        System.out.println("开始合成视频-----");
                        MergeDataService.createMp4(mp4SavePath, new File[]{imgFile}, width, height, mergeVedioType);
                        System.out.println("-----合成视频结束");
                        //合成音频
                        System.out.println("开始合成音频-----");
                        MergeDataService.mergeAudioAndVideo(mp4SavePath, autoPath, mp4SavePath);
                        System.out.println("-----合成音频结束");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    num++;
                }
            }
            //多张图片合成视频
            if (mergeVedioType == PublicEnums.MergeVedioType.MutilImgs.getValue()) {
                String mp4SavePath = imgPath + "\\xiangce.mp4";
                System.out.println("开始合成视频-----");
                MergeDataService.createMp4(mp4SavePath, files.toArray(new File[0]), 1300, 1600, mergeVedioType);
                System.out.println("-----合成视频结束");
            }
            return "操作成功";
        } catch (Exception e) {
            return e.toString();
        }
    }

    /**
     * 多张图片合成单个视频添加音频
     *
     * @param imgPath
     * @param autoPath
     * @return
     */
    public static String makeImagesToSingleVedio(String imgPath, String autoPath) {
        try {
            List<File> files = FileUtil.loopFiles(imgPath, file -> file.isFile() && (file.getName().contains(".jpg") || file.getName().contains(".png")));
            //合成视频先旋转图片
            RotateImage.rotateImgs(files, 270);
            int width = 1300;
            int height = 1600;
            //图片输出路径
            String mp4SavePath = imgPath + "\\merge.mp4";
            File file = new File(mp4SavePath);
            if (file.exists()) {
                file.delete();
            }
            //图片合成视频
            try {
                System.out.println("开始合成视频-----");
                createSingleMp4ByImages(mp4SavePath, files.toArray(new File[0]), width, height);
                System.out.println("-----合成视频结束");
                //截取音频长度
                //转换格式
                if (new File(autoPath).getName().endsWith(".mp3")) {
                    autoPath = new HandleAudioService().converAudio(autoPath);
                }
                FFmpegFrameGrabber grabber = null;
                long durationInSec = 0l;
                try {
                    grabber = new FFmpegFrameGrabber(mp4SavePath);
                    grabber.start();
                    durationInSec = grabber.getFormatContext().duration() / 1000000;
                } catch (Exception e) {
                    throw new RuntimeException(e);
                } finally {
                    grabber.release();
                    grabber.close();
                }
                String newaudiopath = new HandleAudioService().cutAudioByStart(autoPath, durationInSec, "wav");
                //合成音频
                System.out.println("开始合成音频-----");
                HandleVideoService handleVideoService = new HandleVideoService();
                String mp4path = handleVideoService.mergeVediosAndAudio(mp4SavePath, newaudiopath);
                System.out.println("-----合成音频结束");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "操作成功";
        } catch (Exception e) {
            return e.toString();
        }
    }

    /**
     * 多张图片合成单个视频根据图片尺寸进行适配,不添加音频
     *
     * @param imgPath
     * @return
     */
    public static String makeSingleVedio(String imgPath) {
        try {
            List<File> files = FileUtil.loopFiles(imgPath, file -> file.isFile() && (file.getName().contains(".jpg") || file.getName().contains(".JPG") || file.getName().contains(".PNG") || file.getName().contains(".jpeg") || file.getName().contains(".png")));
            if (files == null || files.isEmpty()) {
                return "";
            }
            //图片合成视频
            try {
                System.out.println("图片合成视频开始-----");
                int width = 0;
                int height = 0;
                for (File imgFile : files) {
                    // 读取图片
                    BufferedImage image = ImageIO.read(imgFile);
                    //获取图片的像素数组
                    int curwidth = image.getWidth();
                    int curheight = image.getHeight();
                    if (curheight > curwidth) {
                        width = curwidth;
                        height = curheight;
                    }
                }
                if (height == 0) {
                    BufferedImage image = ImageIO.read(files.get(0));
                    width = image.getWidth();
                    height = image.getHeight();
                }
                for (File file : files) {
                    new HandleVideoService().mergeSingleImgToVideoByFFmpeg(file.getAbsolutePath(), 2, width, height);
                }
                System.out.println("-----图片合成视频结束");
                System.out.println("合并多个视频开始-----");
                new VedioUtils().mergeMulVideosByFFmpeg(imgPath);
                System.out.println("-----合并多个视频结束");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "操作成功";
        } catch (Exception e) {
            return e.toString();
        }
    }

    /**
     * 多张图片合成单个视频根据图片尺寸进行适配,不添加音频
     *
     * @param imgPath
     * @return
     */
    public static String makeSingleVedioAndAudio(String imgPath, String autoPath, int singleImageduration) {
        try {
            List<File> files = FileUtil.loopFiles(imgPath, file -> file.isFile() && (file.getName().contains(".jpg") || file.getName().contains(".png")));
            //图片合成视频
            try {
                System.out.println("图片合成视频开始-----");
                int width = 0;
                int height = 0;
                int totalSize = 0;
                for (File imgFile : files) {
                    // 读取图片
                    BufferedImage image = ImageIO.read(imgFile);
                    //获取图片的像素数组
                    int curwidth = image.getWidth();
                    int curheight = image.getHeight();
                    if (curheight > curwidth) {
                        if (curwidth * curheight > totalSize) {
                            width = curwidth;
                            height = curheight;
                            totalSize = curwidth * curheight;
                        }
                    }
                }
                if (height == 0) {
                    BufferedImage image = ImageIO.read(files.get(0));
                    width = image.getHeight();
                    height = image.getWidth();
                }
                width = 2000;
                height = 3200;
                for (File file : files) {
                    new HandleVideoService().mergeSingleImgToVideoByFFmpeg(file.getAbsolutePath(), singleImageduration, width, height);
                }
                System.out.println("-----图片合成视频结束");
                System.out.println("合并多个视频开始-----");
                String mergeMp4Path = new VedioUtils().mergeMulVideosByFFmpeg(imgPath);
                System.out.println("-----合并多个视频结束");
                //截取音频长度
                //转换格式
                if (new File(autoPath).getName().endsWith(".mp3")) {
                    autoPath = new HandleAudioService().converAudio(autoPath);
                }
                FFmpegFrameGrabber grabber = null;
                long durationInSec = 0l;
                try {
                    grabber = new FFmpegFrameGrabber(mergeMp4Path);
                    grabber.start();
                    durationInSec = grabber.getFormatContext().duration() / 1000000;
                } catch (Exception e) {
                    throw new RuntimeException(e);
                } finally {
                    grabber.release();
                    grabber.close();
                }
                String newaudiopath = new HandleAudioService().cutAudioByStart(autoPath, durationInSec, "wav");
                //合成音频
                System.out.println("开始合成音频-----");
                HandleVideoService handleVideoService = new HandleVideoService();
                String mp4path = handleVideoService.mergeVediosAndAudio(mergeMp4Path, newaudiopath);
                System.out.println("-----合成音频结束");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "操作成功";
        } catch (Exception e) {
            return e.toString();
        }
    }

    /**
     * 单张图片合成单个视频
     *
     * @param imgPath
     * @param autoPath
     * @param mergeVedioType
     * @return
     */
    public static String makeShortvedioByImages(String imgPath, String autoPath, int mergeVedioType) throws Exception {
        FFmpegFrameGrabber grabber = null;
        //读取添加文字后的图片,批量合成视频
        try {
            List<File> imagefiles = FileUtil.loopFiles(imgPath, file -> file.isFile() && (file.getName().contains(".jpg") || file.getName().contains(".png")));
            //合成视频先旋转图片
            RotateImage.rotateImgs(imagefiles, 270);
            int num = 1;
//            int width = 1300;
//            int height = 1600;
            //单张图片合成视频
            grabber = new FFmpegFrameGrabber(autoPath);
            grabber.start();
            //计算音频总时长
            long durationInSec = grabber.getFormatContext().duration() / 1000000;
            if (mergeVedioType == PublicEnums.MergeVedioType.SingleImg.getValue()) {
                for (File imgFile : imagefiles) {
                    // 读取图片
                    BufferedImage image = ImageIO.read(imgFile);
                    //获取图片的像素数组
                    int width = image.getWidth();
                    int height = image.getHeight();
                    //调整图片尺寸
                    String imagepath = ImageHandle.resizeSingleImage(imgFile.getAbsolutePath(), width, height);
                    //图片输出路径
                    String mp4SavePath = imgPath + "\\" + num + ".mp4";
                    //图片合成视频
                    try {
                        System.out.println("开始合成视频-----");
                        MergeDataService.createMp4ByDuration(mp4SavePath, new File[]{imgFile}, width, height, mergeVedioType, Integer.valueOf(durationInSec + ""));
                        System.out.println("-----合成视频结束");
                        //合成音频
                        System.out.println("开始合成视频和音频-----");
                        HandleVideoService handleVideoService = new HandleVideoService();
                        String mp4path = handleVideoService.mergeVediosAndAudio(mp4SavePath, autoPath);
                        System.out.println("-----合成视频和音频结束");
                        //视频合成字幕
                        System.out.println("开始合成字幕-----");
                        new HandleVideoService().mergeVediosBySrt(mp4path);
                        System.out.println("---------合成字幕");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    num++;
                }
            }
            return "操作成功";
        } catch (Exception e) {
            return e.toString();
        } finally {
            grabber.release();
            grabber.close();
        }
    }

    /**
     * 单张图片合成书签视频
     *
     * @param imgPath
     * @param autoPath
     * @return
     */
    public static String makeShortvedioByImagesByTag(String imgPath, String autoPath, String txtPath) {
        //读取添加文字后的图片,批量合成视频
        try {
            List<File> imagefiles = FileUtil.loopFiles(imgPath, file -> file.isFile() && (file.getName().contains(".jpg") || file.getName().contains(".png")));
            //合成视频先旋转图片
            RotateImage.rotateImgs(imagefiles, 270);
            int num = 1;
            //单张图片合成视频
            FFmpegFrameGrabber grabber=null;
            long durationInSec=0;
            try {
                grabber = new FFmpegFrameGrabber(autoPath);
                grabber.start();
                //计算音频总时长
                durationInSec = grabber.getFormatContext().duration() / 1000000;
            } finally {
                if(grabber!=null){
                    grabber.release();
                    grabber.close();
                }
            }
            for (File imgFile : imagefiles) {
                // 读取图片
                BufferedImage image = ImageIO.read(imgFile);
                //获取图片的像素数组
                int width = image.getWidth();
                int height = image.getHeight();
                //判断宽和高是否为偶数
                if (width % 2 != 0) {
                    width = width - 1;
                }
                if (height % 2 != 0) {
                    height = height - 1;
                }
                //视频输出路径
                String mp4SavePath = imgPath + File.separator + num + ".mp4";
                String finalMa4Path = "";
                String secodeMp4Savepath = "";
                //图片合成视频
                try {
                    System.out.println("书签添加文字-----");
                    String firstImagePath = "";
                    try {
                        firstImagePath = new HandleImageMergeService().mergeSingleText2Image(txtPath);
                    } catch (Exception ex) {
                        throw new RuntimeException(ex);
                    }
                    System.out.println("-----书签添加文字结束");
                    System.out.println("开始合成第一个书签视频-----");
                    String firstMp4Savepath = imgPath + File.separator + "first.mp4";
                    createMp4ByFFmpegAndDuration(firstMp4Savepath, firstImagePath, width, 1800, 2);//默认2秒
                    System.out.println("-----合成第一个书签视频结束");
                    System.out.println("开始合成第二个视频-----");
                    createMp4ByFFmpegAndDuration(mp4SavePath, imgFile.getAbsolutePath(), width, height, Integer.valueOf(durationInSec + "") - 2);//将前摇去掉
                    System.out.println("-----合成第二个视频结束");
                    String embedMp4Savepath = "";
                    List<String> files=new ArrayList<>();
                    files.add(firstMp4Savepath);
                    if (width > height) {
                        System.out.println("开始合成背景视频-----");
                        secodeMp4Savepath = imgPath + File.separator + "secode.mp4";
                        createMp4ByFFmpegAndBackDefault(secodeMp4Savepath, width, 1800, 2);//默认2秒
                        System.out.println("-----合成背景视频结束");
                        System.out.println("开始嵌入视频-----");
                        embedMp4Savepath = new HandleVideoService().embedDoubleMp4ByDuration(secodeMp4Savepath, mp4SavePath);//默认2秒
                        System.out.println("-----嵌入视频结束");
                        //合成两个视频  String recursionVideos(List<String> fileList)
                        files.add(embedMp4Savepath);
                        finalMa4Path = new VedioUtils().recursionVideos(files);
                    } else {
                        //合成两个视频
                        files.add(mp4SavePath);
                        finalMa4Path = new VedioUtils().recursionVideos(files);
                    }
                    //合成音频
                    System.out.println("开始合成视频和音频-----");
                    String mp4path = new HandleVideoService().mergeVediosAndAudio(finalMa4Path, autoPath);
                    System.out.println("-----合成视频和音频结束");
                    //视频合成字幕
                    System.out.println("开始合成字幕-----");
                    new HandleVideoService().mergeVediosBySrt(mp4path);
                    System.out.println("---------合成字幕");
                    //删除视频文件
                    File mp4SavePathfile = new File(mp4SavePath);
                    if (mp4SavePathfile.exists()) {
                        mp4SavePathfile.delete();
                    }
                    File firstMp4Savepathfile = new File(firstMp4Savepath);
                    if (firstMp4Savepathfile.exists()) {
                        firstMp4Savepathfile.delete();
                    }
                    File secodeMp4Savepathfile = new File(secodeMp4Savepath);
                    if (secodeMp4Savepathfile.exists()) {
                        secodeMp4Savepathfile.delete();
                    }
                    File file = new File(mp4SavePath);
                    if (file.exists()) {
                        file.delete();
                    }
                    File embedMp4Savepathfile = new File(embedMp4Savepath);
                    if (embedMp4Savepathfile.exists()) {
                        embedMp4Savepathfile.delete();
                    }
                    File finalMa4Pathfile = new File(finalMa4Path);
                    if (finalMa4Pathfile.exists()) {
                        finalMa4Pathfile.delete();
                    }
                    File autoPathfile = new File(autoPath);
                    if(autoPathfile.exists()){
                        autoPathfile.delete();
                    }
                    List<File> vttfilelist = FileUtil.loopFiles(imgPath, vttfile -> vttfile.isFile() && vttfile.getName().endsWith(".vtt"));
                    if(vttfilelist!=null&&vttfilelist.size()>0){
                        for(File vtfile:vttfilelist){
                            vtfile.delete();
                        }
                    }
                    List<File> tagList = FileUtil.loopFiles(imgPath, vttfile -> vttfile.isFile() && vttfile.getName().contains("secode_tag.png"));
                    if(tagList!=null&&tagList.size()>0){
                        for(File tagfile:tagList){
                            tagfile.delete();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                num++;
            }
            return "操作成功";
        } catch (Exception e) {
            return e.toString();
        }
    }

    /**
     * 创建mp4
     *
     * @param mp4SavePath
     * @param width
     * @param height
     * @throws FrameRecorder.Exception
     */
    public static void createMp4(String mp4SavePath, File[] imgFileList, int width, int height, int mergeVedioType) throws FrameRecorder.Exception {
        //视频宽高最好是按照常见的视频的宽高  16：9  或者 9：16
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(mp4SavePath, width, height);
        //设置视频编码层模式
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        recorder.setFormat("mp4");
        // 先默认吧，这个应该属于设置视频的处理模式  不可变(固定)音频比特率
        recorder.setAudioOption("crf", "0");
        //设置视频图像数据格式
        recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
        Java2DFrameConverter converter = new Java2DFrameConverter();//转换器
        try {
            //单张图片合成视频
            if (mergeVedioType == PublicEnums.MergeVedioType.SingleImg.getValue()) {
                // 此处说明每一秒多少帧，即说明1秒会录多少张照片
                recorder.setFrameRate(30); //代表10秒一张图
                // 8000kb/s 这个说明视频每秒大小，值越大图片转过来的压缩率就越小质量就会越高
                recorder.setVideoBitrate(4000000);
                recorder.start();
                //录制一个10秒的视频
                BufferedImage read = ImageIO.read(imgFileList[0]);
                //一秒是25帧 所以要记录25次
                for (int i = 0; i < 10; i++) {
                    for (int j = 0; j < 30; j++) {
                        recorder.record(converter.getFrame(read));
                    }
                }
            }
            //多张图片合成视频
            if (mergeVedioType == PublicEnums.MergeVedioType.MutilImgs.getValue()) {
                recorder.setFrameRate(25);
                recorder.start();
                for (int k = 0; k < imgFileList.length; k++) {
                    //录制一个10秒的动态相册
                    for (int i = 0; i < 45; i++) {
//                    BufferedImage read = ImageIO.read(imgFileList[i]);
                        //一秒是25帧 所以要记录25次
                        for (int j = 0; j < 25; j++) {
                            recorder.record(converter.getFrame(ImageIO.read(imgFileList[k])));
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //最后一定要结束并释放资源
            recorder.stop();
            recorder.release();
        }
    }

    /**
     * 多张图片合成一个视频
     *
     * @param mp4SavePath
     * @param width
     * @param height
     * @throws FrameRecorder.Exception
     */
    public static void createSingleMp4ByImages(String mp4SavePath, File[] imgFileList, int width, int height) throws FrameRecorder.Exception {
        //视频宽高最好是按照常见的视频的宽高  16：9  或者 9：16
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(mp4SavePath, width, height);
        //设置视频编码层模式
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        recorder.setFormat("mp4");
        // 先默认吧，这个应该属于设置视频的处理模式  不可变(固定)音频比特率
        recorder.setAudioOption("crf", "0");
        //设置视频图像数据格式
        recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
        recorder.setVideoBitrate(4000000);
        recorder.setInterleaved(false);

        /**
         *film： 电影、真人类型；
         *animation： 动画；
         *grain： 需要保留大量的grain时用；
         *stillimage： 静态图像编码时使用；
         *psnr： 为提高psnr做了优化的参数；
         *ssim： 为提高ssim做了优化的参数；
         *fastdecode： 可以快速解码的参数；
         *zerolatency：零延迟，用在需要非常低的延迟的情况下，比如电视电话会议的编码。
         */
        recorder.setVideoOption("tune", "stillimage");
        /**
         * ultrafast、superfast、veryfast、faster、fast、medium、slow、slower、veryslow、placebo
         * 这10个选项，从快到慢。
         */
        recorder.setVideoOption("preset", "medium");
        recorder.setVideoOption("crf", "26");
        recorder.setVideoOption("threads", "1");
        recorder.setGopSize(30);// 设置gop,与帧率相同，相当于间隔1秒chan's一个关键帧
        recorder.setTrellis(1);//启用RDOQ算法，优化视频质量 1：在视频码率和视频质量之间取得平衡 2：最大程度优化视频质量（会降低编码速度和提高码率）
        recorder.setMaxDelay(2 * 1000 * 1000);
        recorder.start();
        Java2DFrameConverter converter = new Java2DFrameConverter();//转换器
        try {
            for (int k = 0; k < imgFileList.length; k++) {
                for (int i = 0; i < 1; i++) {//一张图片合成一秒
                    //一秒是30帧 所以要记录30次
                    for (int j = 0; j < 30; j++) {
                        recorder.record(converter.getFrame(ImageIO.read(imgFileList[k])));
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //最后一定要结束并释放资源
            recorder.stop();
            recorder.release();
        }
    }

    /**
     * 创建mp4
     *
     * @param mp4SavePath
     * @param width
     * @param height
     * @throws FrameRecorder.Exception
     */
    public static void createMp4ByDuration(String mp4SavePath, File[] imgFileList, int width, int height, int mergeVedioType, int duration) throws FrameRecorder.Exception {
        File mp4File = new File(mp4SavePath);
        if (mp4File.exists()) {
            mp4File.delete();
        }
        //视频宽高最好是按照常见的视频的宽高  16：9  或者 9：16
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(mp4SavePath, width, height);
        //设置视频编码层模式
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        recorder.setFormat("mp4");
        //设置视频图像数据格式
        recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
        Java2DFrameConverter converter = new Java2DFrameConverter();//转换器
        try {
            //单张图片合成视频
            if (mergeVedioType == PublicEnums.MergeVedioType.SingleImg.getValue()) {
                // 此处说明每一秒多少帧，即说明1秒会录多少张照片
                recorder.setFrameRate(30); //代表10秒一张图
                // 8000kb/s 这个说明视频每秒大小，值越大图片转过来的压缩率就越小质量就会越高
                recorder.setVideoBitrate(4000000);
                recorder.setInterleaved(false);

                /**
                 *film： 电影、真人类型；
                 *animation： 动画；
                 *grain： 需要保留大量的grain时用；
                 *stillimage： 静态图像编码时使用；
                 *psnr： 为提高psnr做了优化的参数；
                 *ssim： 为提高ssim做了优化的参数；
                 *fastdecode： 可以快速解码的参数；
                 *zerolatency：零延迟，用在需要非常低的延迟的情况下，比如电视电话会议的编码。
                 */
                recorder.setVideoOption("tune", "stillimage");
                /**
                 * ultrafast、superfast、veryfast、faster、fast、medium、slow、slower、veryslow、placebo
                 * 这10个选项，从快到慢。
                 */
                recorder.setVideoOption("preset", "medium");
                recorder.setVideoOption("crf", "26");
                recorder.setVideoOption("threads", "1");
                recorder.setGopSize(30);// 设置gop,与帧率相同，相当于间隔1秒chan's一个关键帧
                recorder.setTrellis(1);//启用RDOQ算法，优化视频质量 1：在视频码率和视频质量之间取得平衡 2：最大程度优化视频质量（会降低编码速度和提高码率）
                recorder.setMaxDelay(2 * 1000 * 1000);
                recorder.start();
                //录制一个10秒的视频
                BufferedImage read = ImageIO.read(imgFileList[0]);
                //一秒是30帧 所以要记录30次
                for (int i = 0; i < duration; i++) {
                    for (int j = 0; j < 30; j++) {
                        recorder.record(converter.getFrame(read));
                    }
                }
            }
            //多张图片合成视频
            if (mergeVedioType == PublicEnums.MergeVedioType.MutilImgs.getValue()) {
                recorder.setFrameRate(30);
                recorder.start();
                for (int k = 0; k < imgFileList.length; k++) {
                    //录制一个10秒的动态相册
                    for (int i = 0; i < 45; i++) {
//                    BufferedImage read = ImageIO.read(imgFileList[i]);
                        //一秒是25帧 所以要记录25次
                        for (int j = 0; j < 30; j++) {
                            recorder.record(converter.getFrame(ImageIO.read(imgFileList[k])));
                        }
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //最后一定要结束并释放资源
            recorder.stop();
            recorder.release();
        }
    }

    /**
     * 创建mp4
     *
     * @param mp4SavePath
     * @param width
     * @param height
     * @throws FrameRecorder.Exception
     */
    public static void createMp4ByFFmpegAndDuration(String mp4SavePath, String imgFile, int width, int height,  int duration) throws Exception {
        File mp4File = new File(mp4SavePath);
        if (mp4File.exists()) {
            mp4File.delete();
        }

        List<String> commands = new ArrayList<>();
        commands.add("ffmpeg");
        commands.add("-loop");
        commands.add("1");
        commands.add("-framerate");
        commands.add("30");
        commands.add("-i");
        commands.add(imgFile);
        commands.add("-t");
        commands.add(duration+"");
        commands.add("-c:v");
        commands.add("libx264");
        commands.add("-crf");
        commands.add("18");
        commands.add("-pix_fmt");
        commands.add("yuv420p");
        commands.add("-s");
        commands.add(width+"X"+height);
        commands.add(mp4SavePath);

        String res= FFmpegUtils.execFFmpegCommand(commands);
        System.out.println(res);
    }

    /**
     * 创建mp4指定帧率
     *
     * @param mp4SavePath
     * @param width
     * @param height
     * @throws FrameRecorder.Exception
     */
    public static void createMp4ByFFmpegAndFrameRate(String mp4SavePath, String imgFile, int width, int height,double frameRate, int duration) throws Exception {
        File mp4File = new File(mp4SavePath);
        if (mp4File.exists()) {
            mp4File.delete();
        }

        List<String> commands = new ArrayList<>();
        commands.add("ffmpeg");
        commands.add("-loop");
        commands.add("1");
        commands.add("-framerate");
        commands.add(frameRate+"");
        commands.add("-i");
        commands.add(imgFile);
        commands.add("-t");
        commands.add(duration+"");
        commands.add("-c:v");
        commands.add("libx264");
        commands.add("-crf");
        commands.add("18");
        commands.add("-pix_fmt");
        commands.add("yuv420p");
        commands.add("-s");
        commands.add(width+"X"+height);
        commands.add(mp4SavePath);

        String res= FFmpegUtils.execFFmpegCommand(commands);
        System.out.println(res);
    }

    /**
     * 创建mp4
     *
     * @param mp4SavePath
     * @param width
     * ffmpeg -loop 1 -framerate 30 -i 60 -t 5 -c:v libx264 -crf 18 -pix_fmt yuv420p -vf scale=1258:-1 output.mp4
     * @throws FrameRecorder.Exception
     */
    public static void createMp4ByFFmpegAndScale(String mp4SavePath, String imgFile, int width, int height,  int duration) throws Exception {
        File mp4File = new File(mp4SavePath);
        if (mp4File.exists()) {
            mp4File.delete();
        }

        List<String> commands = new ArrayList<>();
        commands.add("ffmpeg");
        commands.add("-loop");
        commands.add("1");
        commands.add("-framerate");
        commands.add("30");
        commands.add("-i");
        commands.add(imgFile);
        commands.add("-t");
        commands.add(duration+"");
        commands.add("-c:v");
        commands.add("libx264");
        commands.add("-crf");
        commands.add("18");
        commands.add("-pix_fmt");
        commands.add("yuv420p");
        commands.add("-vf");
        if(width==0&&height==0){
            throw  new RuntimeException("宽和高不能同时为0");
        }
        if(width==0){
            commands.add("scale=-1:"+height);
        }
        if(height==0){
            commands.add("scale="+width+":-1");
        }
        if(width>0&&height>0){
            commands.add("scale="+width+":-1");
        }
        commands.add(mp4SavePath);

        String res= FFmpegUtils.execFFmpegCommand(commands);
        System.out.println(res);
    }

    /**
     * 合成背景视频
     *
     * @param mp4SavePath
     * @param width
     * @param height
     * @throws FrameRecorder.Exception
     */
    public static void createMp4ByDurationAndBack(String mp4SavePath, int width, int height, int duration) throws Exception {
        //图片加载到缓冲区
        InputStream inputstream = MergeDataService.class.getClassLoader().getResourceAsStream("tag_s1300.jpg");
        BufferedImage read = ImageIO.read(inputstream);
        if (height == 0) {
            height = read.getHeight();
        }
        //视频宽高最好是按照常见的视频的宽高  16：9  或者 9：16
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(mp4SavePath, width, height);
        //设置视频编码层模式
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        recorder.setFormat("mp4");
        //设置视频图像数据格式
        recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
        Java2DFrameConverter converter = new Java2DFrameConverter();//转换器
        try {
            // 此处说明每一秒多少帧，即说明1秒会录多少张照片
            recorder.setFrameRate(30); //代表10秒一张图
            // 8000kb/s 这个说明视频每秒大小，值越大图片转过来的压缩率就越小质量就会越高
            recorder.setVideoBitrate(4000000);
            recorder.setInterleaved(false);

            /**
             *film： 电影、真人类型；
             *animation： 动画；
             *grain： 需要保留大量的grain时用；
             *stillimage： 静态图像编码时使用；
             *psnr： 为提高psnr做了优化的参数；
             *ssim： 为提高ssim做了优化的参数；
             *fastdecode： 可以快速解码的参数；
             *zerolatency：零延迟，用在需要非常低的延迟的情况下，比如电视电话会议的编码。
             */
            recorder.setVideoOption("tune", "stillimage");
            /**
             * ultrafast、superfast、veryfast、faster、fast、medium、slow、slower、veryslow、placebo
             * 这10个选项，从快到慢。
             */
            recorder.setVideoOption("preset", "medium");
            recorder.setVideoOption("crf", "26");
            recorder.setVideoOption("threads", "1");
            recorder.setGopSize(30);// 设置gop,与帧率相同，相当于间隔1秒chan's一个关键帧
            recorder.setTrellis(1);//启用RDOQ算法，优化视频质量 1：在视频码率和视频质量之间取得平衡 2：最大程度优化视频质量（会降低编码速度和提高码率）
            recorder.setMaxDelay(2 * 1000 * 1000);
            recorder.start();

            //一秒是30帧 所以要记录30次
            for (int i = 0; i < duration; i++) {
                for (int j = 0; j < 30; j++) {
                    recorder.record(converter.getFrame(read));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //最后一定要结束并释放资源
            recorder.stop();
            recorder.release();
            inputstream.close();
        }
    }

    /**
     * 合成背景视频
     *
     * @param mp4SavePath
     * @param width
     * @param height
     * @throws FrameRecorder.Exception
     */
    public static void createMp4ByFFmpegAndBackDefault(String mp4SavePath, int width, int height, int duration) throws Exception {
        //图片加载到缓冲区
        String imgpath= null;
        InputStream inputstream =null;
        FileOutputStream out =null;
        try {
            inputstream = MergeDataService.class.getClassLoader().getResourceAsStream("tag_s1300.jpg");
            BufferedImage read = ImageIO.read(inputstream);
            imgpath = mp4SavePath.replace(".mp4","_tag.png");
             out = new FileOutputStream(imgpath);
            ImageIO.write(read, "png", out);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            inputstream.close();
            out.close();
        }

        List<String> commands = new ArrayList<>();
        commands.add("ffmpeg");
        commands.add("-loop");
        commands.add("1");
        commands.add("-framerate");
        commands.add("30");
        commands.add("-i");
        commands.add(imgpath);
        commands.add("-t");
        commands.add(duration+"");
        commands.add("-c:v");
        commands.add("libx264");
        commands.add("-crf");
        commands.add("18");
        commands.add("-pix_fmt");
        commands.add("yuv420p");
        commands.add("-s");
        commands.add(width+"X"+height);
        commands.add(mp4SavePath);

        String res= FFmpegUtils.execFFmpegCommand(commands);
        System.out.println(res);

    }

    /**
     * 合成音频和视频
     *
     * @param videoPath
     * @param audioPath
     * @param outPut
     * @return
     * @throws Exception
     */
    public static boolean mergeAudioAndVideo(String videoPath, String audioPath, String outPut) throws Exception {
        boolean isCreated = true;
        File file = new File(videoPath);
        if (!file.exists()) {
            return false;
        }
        FrameRecorder recorder = null;
        FrameGrabber grabber1 = null;
        FrameGrabber grabber2 = null;
        try {
            //抓取视频帧
            grabber1 = new FFmpegFrameGrabber(videoPath);
            //抓取音频帧
            grabber2 = new FFmpegFrameGrabber(audioPath);
            grabber1.start();
            grabber2.start();
            //创建录制
            recorder = new FFmpegFrameRecorder(outPut,
                    grabber1.getImageWidth(), grabber1.getImageHeight());

            recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
            recorder.setFormat("mp4");
            //设置视频图像数据格式
            recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
            recorder.setFrameRate(30);
            recorder.setSampleRate(grabber2.getSampleRate());
            // 8000kb/s 这个说明视频每秒大小，值越大图片转过来的压缩率就越小质量就会越高
            recorder.setVideoBitrate(4000000);
            recorder.setAudioOption("crf", "0");
            // 最高质量
            recorder.setAudioQuality(0);
            // 音频比特率
            recorder.setAudioBitrate(grabber2.getAudioBitrate());
            recorder.start();

            Frame frame1;
            Frame frame2;
            //先录入视频
            while ((frame1 = grabber1.grabFrame()) != null) {
                recorder.record(frame1);
            }
            //然后录入音频
            while ((frame2 = grabber2.grabFrame()) != null) {
                recorder.record(frame2);
            }
            grabber1.stop();
            grabber2.stop();
            recorder.stop();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (recorder != null) {
                    recorder.release();
                }
                if (grabber1 != null) {
                    grabber1.release();
                }
                if (grabber2 != null) {
                    grabber2.release();
                }
            } catch (FrameRecorder.Exception e) {
                e.printStackTrace();
            }
        }
        return isCreated;

    }

    /**
     * 批量给图片添加文字
     */
    public static String writeTxt2Img(String imgPath, String txtPath) {
        //读取所有图片
        try {
            File[] files = new File(imgPath).listFiles();
            int initnum = 1;
            StringBuffer flag = new StringBuffer("1");
            int totalMergeImgs = files.length < 30 ? files.length : 30;
            for (File imgFile : files) {
                if (initnum <= totalMergeImgs) {
                    int initLocation = Integer.valueOf(flag.toString());
                    //给图片添加文字
                    AddTextToImg.handleAlltextImg(imgFile.getAbsolutePath(), txtPath, flag, initLocation);
                }
                initnum++;
            }
            return "操作成功";
        } catch (Exception e) {
            return e.toString();
        }
    }

    /**
     * 批量给图片添加长文字
     */
    public static String writeLongTxt2Img(String imgPath, String txtPath) {
        File file = new File(txtPath);
        BufferedReader reader = null;
        try {
            //读取古诗
            reader = new BufferedReader(new FileReader(file));
            String temp;
            int row = 1;
            Map<Integer, List<String>> poemMap = new HashMap<>();
            List<String> poemList = new ArrayList<>();
            List<String> imgpathList = new ArrayList<>();
            while ((temp = reader.readLine()) != null) {
                if (temp.contains("***************")) {
                    poemMap.put(row, new ArrayList<>(poemList));
                    poemList = new ArrayList<>();
                } else if (temp.length() > 3) {
                    poemList.add(temp);
                    row++;
                }
            }
            if (!poemMap.containsKey(row)) {
                poemMap.put(row, poemList);
            }
            //读取图片
            File[] files = new File(imgPath).listFiles();
            for (File imgFile : files) {
                imgpathList.add(imgFile.getAbsolutePath());
            }
            //初始化字体
            Font font = new Font("楷体", Font.BOLD, 35);   //定义字体
            Color color = new Color(6, 3, 3, 241);
            int fontheight = 50;
            for (Map.Entry<Integer, List<String>> entry : poemMap.entrySet()) {
                List<String> poemlist = entry.getValue();
                if (poemlist.size() <= 44) {//2页
                    //写第一个图片
                    int textheight = getTextStartY(imgpathList.get(0), poemlist.size() / 2, fontheight);
                    for (int j = 0; j < poemlist.size() / 2; j++) {
                        //给图片添加文字
                        ImageUtils.drawTextInImg(imgpathList.get(0), poemlist.get(j), imgpathList.get(0), font, textheight, color, 1000, fontheight, true, 1);
                        textheight += fontheight;
                    }
                    imgpathList.remove(0);
                    //写第二个图片
                    textheight = getTextStartY(imgpathList.get(0), poemlist.size() - poemlist.size() / 2, fontheight);
                    for (int h = poemlist.size() / 2; h < poemlist.size(); h++) {
                        //给图片添加文字
                        ImageUtils.drawTextInImg(imgpathList.get(0), poemlist.get(h), imgpathList.get(0), font, textheight, color, 1000, fontheight, true, 1);
                        textheight += fontheight;
                    }
                    imgpathList.remove(0);
                } else if (poemlist.size() <= 66) {//3页
                    //写第一个图片
                    int textheight = getTextStartY(imgpathList.get(0), poemlist.size() / 3, fontheight);
                    for (int j = 0; j < poemlist.size() / 3; j++) {
                        ImageUtils.drawTextInImg(imgpathList.get(0), poemlist.get(j), imgpathList.get(0), font, textheight, color, 1000, fontheight, true, 1);
                        textheight += fontheight;
                    }
                    imgpathList.remove(0);
                    //写第二个图片
                    textheight = getTextStartY(imgpathList.get(0), poemlist.size() / 3, fontheight);
                    for (int h = poemlist.size() / 3; h < poemlist.size() * 2 / 3; h++) {
                        ImageUtils.drawTextInImg(imgpathList.get(0), poemlist.get(h), imgpathList.get(0), font, textheight, color, 1000, fontheight, true, 1);
                        textheight += fontheight;
                    }
                    imgpathList.remove(0);
                    //写第二个图片
                    textheight = getTextStartY(imgpathList.get(0), poemlist.size() - poemlist.size() * 2 / 3, fontheight);
                    for (int k = poemlist.size() * 2 / 3; k < poemlist.size(); k++) {
                        ImageUtils.drawTextInImg(imgpathList.get(0), poemlist.get(k), imgpathList.get(0), font, textheight, color, 1000, fontheight, true, 1);
                        textheight += fontheight;
                    }
                    imgpathList.remove(0);
                } else if (poemlist.size() <= 88) {//4页

                }
            }
            return "操作成功";
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return "操作成功";
    }


    /**
     * 文字的起始高
     *
     * @param imgPath
     * @param totaline
     * @param fontheight
     * @return
     * @throws Exception
     */
    private static int getTextStartY(String imgPath, int totaline, int fontheight) throws Exception {
        int textheight = (totaline) * fontheight;
        BufferedImage bimage = ImageUtils.imageIoRead(imgPath);
        int imgHerght = bimage.getHeight();
        //居中显示
        textheight = (imgHerght - textheight) / 2;

        return textheight;
    }


}
